﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using MaxFramework;

namespace PhotoOrganizer
{
    public class FileHandler
    {
        public delegate void DelUpdateStatus(int pTotal, int pCurrent);
        public static List<PhotoOrganizer.File> GetImageList()
        {
            if (!System.IO.File.Exists(Common.Constans.FileListPath))
                return new List<File>();
            else
            {
                var tXML = System.IO.File.ReadAllText(Common.Constans.FileListPath);
                return tXML.FromXML<List<PhotoOrganizer.File>>();
            }
        }

        public static List<PhotoOrganizer.File> GetImageOrderByCreatedDateTimeList()
        {
            return FileHandler.GetImageList().OrderBy(t => t.CreatedDateTime).ToList();
        }

        public static void SaveFileList(List<File> pList)
        {
            MaxFramework.Serialization.Serializer.WriteObjectToXmlFileUnicode(pList, Common.Constans.FileListPath);
        }

        public static void GatherFileInfo(object param)
        {
            var a = (IList<string>)((object[])param)[0];
            var b = (IList<string>)((object[])param)[1];
            var c = (DelUpdateStatus)((object[])param)[2];
            GatherFileInfo(a, b, c);
        }

        public static void GatherFileInfo(IList<string> pSources, IList<string> pExtentions, DelUpdateStatus pUpdateStatus)
        {
            var list = new List<PhotoOrganizer.File>();
            var deletelist = new List<string>();
            List<string> totalfiles = new List<string>();

            foreach (var ext in pExtentions)
            {
                foreach (var src in pSources)
                {
                    var files = System.IO.Directory.GetFiles(src, ext, System.IO.SearchOption.AllDirectories);
                    totalfiles.AddRange(files);
                }
            }

            int current = 0;

            foreach (var file in totalfiles)
            {
                try
                {

                    //if (tHashList.ContainsKey(hash))
                    //{
                    //    System.Diagnostics.Debug.WriteLine(string.Format("duplicate {0} existing {1}.", file, tHashList[hash].OriginalSource));
                    //}
                    //else
                    //{
                    //    tHashList.Add(hash, new Image() { ImageHash = hash, DatePictureTaken = Tools.Util.Drawing.ImageHandler.GetDatePictureTaken(file), OriginalSource = file });
                    //}

                    var addFile = new File() { OriginalSource = file };

                    //if (addFile.IsImage)
                    //{
                    //    using (System.IO.FileStream fs = new System.IO.FileStream(file, System.IO.FileMode.Open))
                    //    {
                    //        using (System.IO.BinaryReader br = new System.IO.BinaryReader(fs))
                    //        {
                    //            var bytes = br.ReadBytes((int)br.BaseStream.Length);

                    //            var temp = new MD5CryptoServiceProvider().ComputeHash(bytes);
                    //            addFile.FileHash = temp;

                    //            br.Close();
                    //        }
                    //        fs.Close();
                    //    }
                    //}


                    if (addFile.IsImage)
                    {
                        //var image = System.Drawing.Image.FromFile(file);
                        //addFile.ImageHash = image.GetHashCode();
                        //image.Dispose();
                        //image = null;
                        try
                        {
                            addFile.CreatedDateTime = MaxFramework.Drawing.ImageHandler.GetDatePictureTaken(file);
                        }
                        catch
                        {
                            addFile.CreatedDateTime = (new System.IO.FileInfo(file)).LastWriteTime;
                        }
                    }
                    else
                    {
                        addFile.CreatedDateTime = (new System.IO.FileInfo(file)).LastWriteTime;
                    }

                    list.Add(addFile);
                }
                catch
                {
                    System.IO.File.Move(file, @"E:\BASE\BADFILES\" + System.IO.Path.GetFileName(file));
                }

                current++;
                pUpdateStatus(totalfiles.Count, current);

            }

            FileHandler.SaveFileList(list);
        }

        public static void OrganizeFiles(object param)
        {
            var a = (string)((object[])param)[0];
            var b = (DelUpdateStatus)((object[])param)[1];
            OrganizeFiles(a, b);
        }

        public static void OrganizeFiles(string pDestination, DelUpdateStatus pUpdateStatus)
        {
            var list = FileHandler.GetImageOrderByCreatedDateTimeList();
            long tTotalSize = 0;

            SortedList<int, SortedList<string, List<File>>> splitlist = new SortedList<int, SortedList<string, List<File>>>();

            splitlist.Add(splitlist.Count + 1, new SortedList<string, List<File>>());

            int current = 0;
            int total = list.Count;

            foreach (var image in list)
            {
                var percent = (current % list.Count) / 100;

                var tInfo = new System.IO.FileInfo(image.OriginalSource);

                tTotalSize += tInfo.Length;

                string tDateKey = image.CreatedDateTime.Value.ToString("yyyy-MM");

                if (!splitlist[splitlist.Count].ContainsKey(tDateKey))
                    splitlist[splitlist.Count].Add(tDateKey, new List<File>());

                if (Decimal.Divide(tTotalSize, 1073741824) > (decimal)4.3)
                {
                    tTotalSize = tInfo.Length;
                    splitlist.Add(splitlist.Count + 1, new SortedList<string, List<File>>());
                    splitlist[splitlist.Count].Add(tDateKey, new List<File>());
                }

                splitlist[splitlist.Count][tDateKey].Add(image);

                current++;

                pUpdateStatus(total, current);
            }

            current = 0;

            foreach (int tDvdkey in splitlist.Keys)
            {
                string tCurDir = string.Format("{0}\\DVD_{1}\\", pDestination, tDvdkey);
                if (!System.IO.Directory.Exists(tCurDir))
                    System.IO.Directory.CreateDirectory(tCurDir);

                var tDateToImageList = splitlist[tDvdkey];

                foreach (string tDateKey in tDateToImageList.Keys)
                {
                    string tDateDir = string.Format("{0}{1}\\", tCurDir, tDateKey);

                    if (!System.IO.Directory.Exists(tDateDir))
                        System.IO.Directory.CreateDirectory(tDateDir);

                    foreach (var tImage in tDateToImageList[tDateKey])
                    {
                        var filename = tImage.CreatedDateTime.Value.ToString("yyyy-MM-dd-HH-mm-ss");
                        var ext = System.IO.Path.GetExtension(tImage.OriginalSource);

                        string newfile = tDateDir + filename + ext;
                        int i = 0;

                        while (System.IO.File.Exists(newfile))
                        {

                            i++;
                            newfile = string.Format("{0}{1}-{2:00}{3}", tDateDir, filename, i, ext);
                        }

                        tImage.NewSource = newfile;

                        System.IO.File.Move(tImage.OriginalSource, newfile);

                        current++;
                    }

                }

                pUpdateStatus(total, current);
            }


        }

        public static void FindDuplicates()
        {
            SortedList<int, string> hashSourceList = new SortedList<int, string>();

            var list = FileHandler.GetImageOrderByCreatedDateTimeList();

            var duplicateList = new List<string>();

            foreach (var item in list)
            {
                item.comapredTo = new List<string>();

                foreach (var compareitem in list)
                {
                    if (duplicateList.Contains(compareitem.OriginalSource)) continue;
                    if (item == compareitem) continue;
                    if (item.Extention != compareitem.Extention) continue;
                    if (item.CreatedDateTime != compareitem.CreatedDateTime) continue;
                    if (item.comapredTo.Contains(compareitem.OriginalSource)) continue;
                    if (compareitem.comapredTo.Contains(item.OriginalSource)) continue;
                    //if (item.FileHash == null || compareitem.FileHash == null) continue;

                    if (item.Compare(compareitem))
                        duplicateList.Add(item.OriginalSource);

                    item.comapredTo.Add(compareitem.OriginalSource);
                    compareitem.comapredTo.Add(compareitem.OriginalSource);
                }
            }

            foreach (string dup in duplicateList)
            {
                var filename = System.IO.Path.GetFileName(dup);
                System.IO.File.Move(dup, @"E:\BASE\DUPLICATES\" + filename);
            }
        }
    }
}
